﻿using System;
using System.Linq;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    /// 针对<see cref="IServiceCollection"/>进行扩展
    /// </summary>
    /// <creator>marc</creator>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <typeparam name="TImplementation">实现类的约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <returns></returns>
        public static IServiceCollection AddSingletonIfNotExists<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddSingleton<TService, TImplementation>();
            }

            return services;
        }
        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <param name="implementationInstance">实现类</param>
        /// <returns></returns>
        public static IServiceCollection AddSingletonIfNotExists<TService>(this IServiceCollection services, TService implementationInstance) where TService : class
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddSingleton(implementationInstance);
            }

            return services;
        }

        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <typeparam name="TImplementation">实现类的约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <returns></returns>
        public static IServiceCollection AddScopedIfNotExists<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddScoped<TService, TImplementation>();
            }

            return services;
        }
        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <param name="implementationFactory">实现类</param>
        /// <returns></returns>
        public static IServiceCollection AddScopedIfNotExists<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddScoped(implementationFactory);
            }

            return services;
        }

        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <typeparam name="TImplementation">实现类的约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <returns></returns>
        public static IServiceCollection AddTransientIfNotExists<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddTransient<TService, TImplementation>();
            }

            return services;
        }
        /// <summary>
        /// 仅当服务不存在时，才添加进去
        /// </summary>
        /// <typeparam name="TService">服务约束</typeparam>
        /// <param name="services">服务列表</param>
        /// <param name="implementationFactory">实现类</param>
        /// <returns></returns>
        public static IServiceCollection AddTransientIfNotExists<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
        {
            var existingService = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (existingService == null)
            {
                services.AddTransient(implementationFactory);
            }

            return services;
        }
    }
}